package com.express.common;

import java.sql.Array;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.apache.ibatis.type.*;

//// 继承自BaseTypeHandler<Object[]> 使用时传入的参数一定要是Object[]，例如 int[]是 Object, 不是Object[]，所以传入int[] 会报错的
//public class ArrayTypeHandler extends BaseTypeHandler<Object[]> {
//
//    private static final String TYPE_NAME_VARCHAR = "varchar";
//    private static final String TYPE_NAME_INTEGER = "integer";
//    private static final String TYPE_NAME_BOOLEAN = "boolean";
//    private static final String TYPE_NAME_NUMERIC = "numeric";
//
//    @Override
//    public void setNonNullParameter(PreparedStatement ps, int i, Object[] parameter,
//            JdbcType jdbcType) throws SQLException {
//
//        /* 这是ibatis时的做法
//        StringBuilder arrayString = new StringBuilder("{");
//
//        for (int j = 0, l = parameter.length; j < l; j++) {
//            arrayString.append(parameter[j]);
//            if (j < l - 1) {
//                arrayString.append(",");
//            }
//        }
//
//        arrayString.append("}");
//
//        ps.setString(i, arrayString.toString());
//        */
//
//        String typeName = null;
//        if (parameter instanceof Integer[]) {
//            typeName = TYPE_NAME_INTEGER;
//        } else if (parameter instanceof String[]) {
//            typeName = TYPE_NAME_VARCHAR;
//        } else if (parameter instanceof Boolean[]) {
//            typeName = TYPE_NAME_BOOLEAN;
//        } else if (parameter instanceof Double[]) {
//            typeName = TYPE_NAME_NUMERIC;
//        }
//
//        if (typeName == null) {
//            throw new TypeException("ArrayTypeHandler parameter typeName error, your type is " + parameter.getClass().getName());
//        }
//                // 这3行是关键的代码，创建Array，然后ps.setArray(i, array)就可以了
//        Connection conn = ps.getConnection();
//        Array array = conn.createArrayOf(typeName, parameter);
//        ps.setArray(i, array);
//    }
//
//    @Override
//    public Object[] getNullableResult(ResultSet rs, String columnName)
//            throws SQLException {
//
//        return getArray(rs.getArray(columnName));
//    }
//
//    @Override
//    public Object[] getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
//
//        return getArray(rs.getArray(columnIndex));
//    }
//
//    @Override
//    public Object[] getNullableResult(CallableStatement cs, int columnIndex)
//            throws SQLException {
//
//        return getArray(cs.getArray(columnIndex));
//    }
//
//    private Object[] getArray(Array array) {
//
//        if (array == null) {
//            return null;
//        }
//
//        try {
//            return (Object[]) array.getArray();
//        } catch (Exception e) {
//        }
//
//        return null;
//    }
//}

import org.apache.ibatis.type.*;
import java.sql.*;

@MappedJdbcTypes(JdbcType.ARRAY)
@MappedTypes(String[].class)
public class ArrayTypeHandler extends BaseTypeHandler<Object[]> {
    private static final String TYPE_NAME_VARCHAR = "varchar";
    private static final String TYPE_NAME_INTEGER = "integer";
    private static final String TYPE_NAME_BOOLEAN = "boolean";
    private static final String TYPE_NAME_NUMERIC = "numeric";
    private static final String TYPE_NAME_BIGINT  = "bigint";

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Object[] parameter, JdbcType jdbcType) throws SQLException {
        String typeName = null;
        if (parameter instanceof Integer[]) {
            typeName = TYPE_NAME_INTEGER;
        } else if (parameter instanceof String[]) {
            typeName = TYPE_NAME_VARCHAR;
        } else if (parameter instanceof Boolean[]) {
            typeName = TYPE_NAME_BOOLEAN;
        } else if (parameter instanceof Double[]) {
            typeName = TYPE_NAME_NUMERIC;
        } else if (parameter instanceof Long[]) {
            typeName = TYPE_NAME_BIGINT;
        }

        if (typeName == null) {
            throw new TypeException("ArrayTypeHandler parameter typeName error, your type is " + parameter.getClass().getName());
        }

        // 这3行是关键的代码，创建Array，然后ps.setArray(i, array)就可以了
        Connection conn = ps.getConnection();
        Array array = conn.createArrayOf(typeName, parameter);
        ps.setArray(i, array);
    }

    @Override
    public Object[] getNullableResult(ResultSet resultSet, String s) throws SQLException {
        return getArray(resultSet.getArray(s));
    }

    @Override
    public Object[] getNullableResult(ResultSet resultSet, int i) throws SQLException {
        return getArray(resultSet.getArray(i));
    }

    @Override
    public Object[] getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
        return getArray(callableStatement.getArray(i));
    }

    private Object[] getArray(Array array) {
        if (array == null) {
            return null;
        }
        try {
            return (Object[]) array.getArray();
        } catch (Exception e) {
        }
        return null;
    }

}
